﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using CivilleWP7.CivilleDataServiceReference;
using System.Device.Location;
using Microsoft.Phone.Controls.Maps;
using Microsoft.Phone.Controls.Maps.Platform;
using CivilleWP7.RouteServiceReference;
using System.Windows.Media.Imaging;

namespace CivilleWP7.Views.Pages
{
    public partial class TaskDetail : PhoneApplicationPage
    {
        private static Task task;
        private GeoCoordinateWatcher watcher;
        private RouteServiceClient routeClient;
        private RouteRequest routeRequest;
        private Pushpin taskPin;
        private Pushpin userPin;
        private bool IsLightTheme;

        public static Task Task
        {
            get { return TaskDetail.task; }
            set { TaskDetail.task = value; }
        }
        public TaskDetail()
        {
            InitializeComponent();
            watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High); // using high accuracy
            watcher.MovementThreshold = 20; // use MovementThreshold to ignore noise in the signal
            watcher.StatusChanged += new EventHandler<GeoPositionStatusChangedEventArgs>(watcher_StatusChanged);
            watcher.PositionChanged += new EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>(watcher_PositionChanged);
            watcher.Start();
            setBackground();
        }
        void checkThemeColor()
        {
            var visibility = (Visibility)Application.Current.Resources["PhoneLightThemeVisibility"];
            if (visibility == Visibility.Visible)
                IsLightTheme = true;
            else
                IsLightTheme = false;
        }
        void setBackground()
        {
            checkThemeColor();
            ImageBrush myBrush = new ImageBrush();
            if(IsLightTheme)
                myBrush.ImageSource=new BitmapImage(new Uri("/Resources/Images/Backgroundwhite.jpg",UriKind.Relative));
            else
                myBrush.ImageSource = new BitmapImage(new Uri("/Resources/Images/Background.jpg",UriKind.Relative));
            LayoutRoot.Background=myBrush;
        }

        void watcher_StatusChanged(object sender, GeoPositionStatusChangedEventArgs e)
        {
            switch (e.Status)
            {
                case GeoPositionStatus.Disabled:
                    // The Location Service is disabled or unsupported.
                    // Check to see whether the user has disabled the Location Service.
                    if (watcher.Permission == GeoPositionPermission.Denied)
                    {
                        MessageBoxButton ok = new MessageBoxButton();
                        MessageBox.Show("GeoLocation is disabled. Please enable it to detect tasks near you.", "Civille Application", ok);
                    }
                    else
                    {
                        MessageBoxButton ok = new MessageBoxButton();
                        MessageBox.Show("GeoLocation is not functioning on this device. You will not be able to detect tasks near you.", "Civille Application", ok);
                    }
                    break;

                case GeoPositionStatus.Initializing:
                    // The Location Service is initializing.
                    break;

                case GeoPositionStatus.NoData:
                    // The Location Service is working, but it cannot get location data.
                    // Alert the user and enable the Stop Location button.
                    MessageBoxButton okay = new MessageBoxButton();
                    MessageBox.Show("GeoLocation cannot retrieve location information.", "Civille Application", okay);
                    break;

                case GeoPositionStatus.Ready:
                    // The Location Service is working and is receiving location data.
                    break;
            }
        }

        void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
        {
            try
            {
                watcher.PositionChanged -= new EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>(watcher_PositionChanged);
                MapControl.Center = new GeoCoordinate(e.Position.Location.Latitude, e.Position.Location.Longitude);
                MapControl.ZoomLevel = 10;

                routeClient = new RouteServiceClient("BasicHttpBinding_IRouteService");
                routeClient.CalculateRouteCompleted += new EventHandler<CalculateRouteCompletedEventArgs>(routeClient_CalculateRouteCompleted);
                routeRequest = new RouteRequest();
                routeRequest.Credentials = new CivilleWP7.RouteServiceReference.Credentials();
                routeRequest.Credentials.ApplicationId = ((ApplicationIdCredentialsProvider)MapControl.CredentialsProvider).ApplicationId;
                routeRequest.Options = new RouteOptions();
                routeRequest.Options.RoutePathType = RoutePathType.Points;
                routeRequest.Waypoints = new System.Collections.ObjectModel.ObservableCollection<Waypoint>();
                Waypoint taskPoint = new Waypoint();
                Waypoint userPoint = new Waypoint();
                CivilleWP7.RouteServiceReference.Location taskLocation = new RouteServiceReference.Location();
                CivilleWP7.RouteServiceReference.Location userLocation = new RouteServiceReference.Location();
                taskLocation.Latitude = Task.Latitude;
                taskLocation.Longitude = Task.Longitude;
                userLocation.Latitude = e.Position.Location.Latitude;
                userLocation.Longitude = e.Position.Location.Longitude;
                taskPoint.Location = taskLocation;
                userPoint.Location = userLocation;
                routeRequest.Waypoints.Add(taskPoint);
                routeRequest.Waypoints.Add(userPoint);

                userPin = new Pushpin();
                userPin.Location = new GeoCoordinate(e.Position.Location.Latitude, e.Position.Location.Longitude);
                userPin.Content = "You are here";
                userPin.Background = App.Current.Resources["PhoneAccentBrush"] as Brush;
                userPin.Foreground = new SolidColorBrush(Colors.White);
                //PushPinLayer.AddChild(userPin, new GeoCoordinate(e.Position.Location.Latitude, e.Position.Location.Longitude));
            }
            catch (Exception)
            { 
                //probably some route service bugs
            }
        }

        private void doneBtn_Click(object sender, RoutedEventArgs e)
        {
            NavigationService.Navigate(new Uri("/Views/Pages/VerifyTask.xaml?id=" + task.ID, UriKind.Relative));
        }

        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);

            try
            {
                this.TitleTextBlock.Text = Task.Title;
                this.DescriptionTextBlock.Text = Task.Description;
                this.PointsTextBlock.Text = Task.Points.ToString() + " points";
                if (Task.Logo != null && !Task.Logo.Equals(""))
                {
                    this.Logo.Source = new BitmapImage(new Uri(Task.Logo, UriKind.Absolute));
                }

                taskPin = new Pushpin();
                Microsoft.Phone.Controls.Maps.Platform.Location location = new Microsoft.Phone.Controls.Maps.Platform.Location();
                location.Latitude = Task.Latitude;
                location.Longitude = Task.Longitude;
                taskPin.Location = location;
                taskPin.Content = task.Title;
                taskPin.Background = App.Current.Resources["PhoneAccentBrush"] as Brush;
                taskPin.Foreground = new SolidColorBrush(Colors.White);
            }
            catch (Exception)
            { 
                
            }
        }

        void routeClient_CalculateRouteCompleted(object sender, CalculateRouteCompletedEventArgs e)
        {
            // If the route calculate was a success and contains a route, then draw the route on the map.
            if ((e.Result.ResponseSummary.StatusCode == ResponseStatusCode.Success) & (e.Result.Result.Legs.Count != 0))
            {
                // Set properties of the route line you want to draw.
                Color routeColor = (Color)Application.Current.Resources["PhoneAccentColor"];
                SolidColorBrush routeBrush = new SolidColorBrush(routeColor);
                MapPolyline routeLine = new MapPolyline();
                routeLine.Locations = new LocationCollection();
                routeLine.Stroke = routeBrush;
                routeLine.Opacity = 0.65;
                routeLine.StrokeThickness = 5.0;

                // Retrieve the route points that define the shape of the route.
                foreach (RouteServiceReference.Location p in e.Result.Result.RoutePath.Points)
                {
                    routeLine.Locations.Add(new System.Device.Location.GeoCoordinate(p.Latitude, p.Longitude));
                }

                // Add the route line to the new layer.
                RouteLayer.Children.Add(routeLine);
                PushPinLayer.Children.Add(userPin);
                PushPinLayer.Children.Add(taskPin);

                GeoCoordinate rectCenter = new GeoCoordinate();
                rectCenter.Latitude = (routeLine.Locations[0].Latitude + routeLine.Locations[routeLine.Locations.Count - 1].Latitude) / 2;
                rectCenter.Longitude = (routeLine.Locations[0].Longitude + routeLine.Locations[routeLine.Locations.Count - 1].Longitude) / 2;

                double width = Math.Abs(routeLine.Locations[0].Latitude - routeLine.Locations[routeLine.Locations.Count - 1].Latitude);
                double height = Math.Abs(routeLine.Locations[0].Longitude - routeLine.Locations[routeLine.Locations.Count - 1].Longitude);

                // Figure the rectangle which encompasses the route. This is used later to set the map view.
                // Due to the fact that Latitude = height, I will swap the parameters (blame it on Nick)
                LocationRect rect = new LocationRect(rectCenter, height, width);

                // Set the map view using the rectangle which bounds the rendered route.
                MapControl.SetView(rect);
            }
        }

        private void MapControl_MapResolved(object sender, EventArgs e)
        {
            try
            {
                if (Math.Sqrt((taskPin.Location.Longitude - userPin.Location.Longitude) * (taskPin.Location.Longitude - userPin.Location.Longitude) + (taskPin.Location.Latitude - userPin.Location.Latitude) * (taskPin.Location.Latitude - userPin.Location.Latitude)) > 10)
                {
                    PushPinLayer.Children.Add(taskPin);
                    MapControl.Center = new GeoCoordinate(taskPin.Location.Latitude, taskPin.Location.Longitude);
                    MessageBox.Show("Cannot calculate route, you are too far away.");
                }
                else
                {
                    routeClient.CalculateRouteAsync(routeRequest);
                }
            }
            catch (Exception)
            { 
                
            }
            MapControl.MapResolved -= new EventHandler(MapControl_MapResolved);
        }

        protected override void OnOrientationChanged(OrientationChangedEventArgs e)
        {
            base.OnOrientationChanged(e);
            if (e.Orientation == PageOrientation.LandscapeLeft || e.Orientation==PageOrientation.LandscapeRight || e.Orientation==PageOrientation.Landscape)
            {
                ColumnDefinition colDef1 = new ColumnDefinition();
                colDef1.Width = new GridLength(100, GridUnitType.Star);
                this.LayoutRoot.ColumnDefinitions.Clear();
                this.LayoutRoot.ColumnDefinitions.Add(colDef1);
                RowDefinition rowDef1 = new RowDefinition();
                rowDef1.Height = new GridLength(20, GridUnitType.Star);
                RowDefinition rowDef2 = new RowDefinition();
                rowDef2.Height = new GridLength(65, GridUnitType.Star);
                RowDefinition rowDef3 = new RowDefinition();
                rowDef3.Height = new GridLength(15, GridUnitType.Star);
                this.LayoutRoot.RowDefinitions.Clear();
                this.LayoutRoot.RowDefinitions.Add(rowDef1);
                this.LayoutRoot.RowDefinitions.Add(rowDef2);
                this.LayoutRoot.RowDefinitions.Add(rowDef3);
                MapControl.SetValue(Grid.RowProperty, 1);
                MapControl.SetValue(Grid.ColumnProperty, 0);
                MapControl.SetValue(Grid.RowSpanProperty, 1);
                MapControl.SetValue(Grid.ColumnSpanProperty, 1);
                DoneButton.SetValue(Grid.ColumnSpanProperty, 1);
                this.DescriptionTextBlock.Visibility = Visibility.Collapsed;
            }
            else
            {
                ColumnDefinition colDef1 = new ColumnDefinition();
                colDef1.Width = new GridLength(60, GridUnitType.Star);
                ColumnDefinition colDef2 = new ColumnDefinition();
                colDef2.Width = new GridLength(40, GridUnitType.Star);
                this.LayoutRoot.ColumnDefinitions.Clear();
                this.LayoutRoot.ColumnDefinitions.Add(colDef1);
                this.LayoutRoot.ColumnDefinitions.Add(colDef2);
                RowDefinition rowDef1 = new RowDefinition();
                rowDef1.Height = new GridLength(15, GridUnitType.Star);
                RowDefinition rowDef2 = new RowDefinition();
                rowDef2.Height = new GridLength(10, GridUnitType.Star);
                RowDefinition rowDef3 = new RowDefinition();
                rowDef3.Height = new GridLength(25, GridUnitType.Star);
                RowDefinition rowDef4 = new RowDefinition();
                rowDef4.Height = new GridLength(40, GridUnitType.Star);
                RowDefinition rowDef5 = new RowDefinition();
                rowDef5.Height = new GridLength(10, GridUnitType.Star);
                this.LayoutRoot.RowDefinitions.Clear();
                this.LayoutRoot.RowDefinitions.Add(rowDef1);
                this.LayoutRoot.RowDefinitions.Add(rowDef2);
                this.LayoutRoot.RowDefinitions.Add(rowDef3);
                this.LayoutRoot.RowDefinitions.Add(rowDef4);
                MapControl.SetValue(Grid.RowProperty, 3);
                MapControl.SetValue(Grid.ColumnProperty, 0);
                DoneButton.SetValue(Grid.ColumnSpanProperty, 3);
                MapControl.SetValue(Grid.RowSpanProperty, 1);
                MapControl.SetValue(Grid.ColumnSpanProperty, 2);
                this.LayoutRoot.RowDefinitions.Add(rowDef5);
                this.DescriptionTextBlock.Visibility = Visibility.Visible;
            }

        }
    }
}
